package com.dale.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dale.common.dto.EditUserDto;
import com.dale.common.dto.RegistDto;
import com.dale.common.dto.UserDto;
import com.dale.common.lang.Result;
import com.dale.entity.User;
import com.dale.mapper.RoleMapper;
import com.dale.service.UserService;
import com.dale.shiro.AccountProfile;
import com.dale.util.QiniuUtils;
import com.dale.util.SaltUtil;
import com.dale.util.ShiroUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author  ：MarkerHub
 * @since 2020-05-25
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;


    @Autowired
    RoleMapper roleMapper;
    //    @RequiresAuthentication
//    @GetMapping("/index")
//    public Result index() {
//        User user = userService.getById(1L);
//        return Result.succ(user);
//    }

    //该接口 未使用到
//    @PostMapping("/save")
//    public Result save(@Validated @RequestBody User user) {
//        return Result.succ(user);
//    }


    @RequiresAuthentication
    @RequestMapping("/getUserByJWT")
    public Result getUserByJWT(){
        //如果浏览器 有token 但是没 userinfo 这是由于 sessionStorage 和 localStorage的区别造成的
        //然后浏览器调用一下
        AccountProfile user = ShiroUtil.getProfile();

        return Result.succ(MapUtil.builder()
                .put("id", user.getId())
                .put("username", user.getUsername())
                .put("avatar", user.getAvatar())
                .put("email", user.getEmail())
                .put("description", user.getDescription())
                .put("role", roleMapper.getUserRole(user.getId()))
                .map()
        );

    }



    /**
     * <p>
     * 所以用shiro 获取当前登录的用户
     *
     * @param editUserDto
     * @return
     */
    @RequiresAuthentication
    @PostMapping("/editUser")
    public Result editUser(@Validated @RequestBody EditUserDto editUserDto) {

        //获取当前登录的用户
        Long id = ShiroUtil.getProfile().getId();
        //查到原来的用户
        User oldUser = userService.getById(id);

        Assert.notNull(oldUser, "该用户不存在");

        //判断用户名是否重复
        User user = userService.getOne(new QueryWrapper<User>().eq("username", editUserDto.getUsername()));

        if (user == null) {
            //表明没这个用户
            //更新用户
            BeanUtil.copyProperties(editUserDto, oldUser);
            userService.updateById(oldUser);
            return Result.succ(MapUtil.builder()
                    .put("id", oldUser.getId())
                    .put("username", oldUser.getUsername())
                    .put("avatar", oldUser.getAvatar())
                    .put("email", oldUser.getEmail())
                    .put("description", oldUser.getDescription())
                    .map());
        } else {
            if (user.getId() != oldUser.getId()) {
                //不是同一个人 但名字相同
                return Result.fail("该用户名已被某位使用");
            } else {
                //还是这个人 只是用户名没变
                BeanUtil.copyProperties(editUserDto, oldUser);
                userService.updateById(oldUser);
                return Result.succ(MapUtil.builder()
                        .put("id", oldUser.getId())
                        .put("username", oldUser.getUsername())
                        .put("avatar", oldUser.getAvatar())
                        .put("email", oldUser.getEmail())
                        .put("description", oldUser.getDescription())
                        .map());
            }
        }

    }


    /**
     * 自定义实现注册
     *
     * @param registDto
     * @return
     */
    @PostMapping("/register")
    public Result register(@Validated @RequestBody RegistDto registDto) {

        String username = registDto.getUsername();

        if (userService.getOne(new QueryWrapper<User>().eq("username", username)) != null) {
            return Result.fail("该用户名已存在");
        }

        User user = new User();

        //加盐 并 hash
        registDto.setPassword(SaltUtil.encryption(registDto.getPassword(),SaltUtil.getSalt()));

        BeanUtil.copyProperties(registDto, user);

        user.setCreated(LocalDateTime.now());

        userService.save(user);

        return Result.succ(200, "注册成功", MapUtil.builder()
                .put("username", registDto.getUsername())
                .map());

    }


    /**
     * 管理员 管理所有用户
     * ：可查看所有用户
     * ：可修改所有用户statue （封号）
     * ：可对文章删除（逻辑删除）
     *
     * @return
     */
    @RequiresRoles("admin")
    @RequiresAuthentication
    @GetMapping("list")
    public Result listUser(@RequestParam(defaultValue = "1") Integer currentPage) {
        //直接返回权限太大  包括了密码
        //所有将用户封装到AccountProfile            本来应该重写service的  。。。
//        return Result.succ(userService.list());

        //MybatisPlus分页  参数(起始页面、个数)
        Page page = new Page(currentPage, 7);
        //根据创建时间倒叙（最新在前）
        //提示：这里也可以逻辑删除判断筛选哈
        IPage pageData = userService.page(page, new QueryWrapper<User>().orderByAsc("username"));

        List<User> records = pageData.getRecords();

//        System.out.println("old"+records);

        ArrayList<UserDto> newUserList = new ArrayList<>();


        for (User user : records) {
            UserDto userDto = new UserDto();
            BeanUtil.copyProperties(user, userDto);
            newUserList.add(userDto);
        }


//        System.out.println("new"+newUserList);


        pageData.setRecords(newUserList);

        return Result.succ(pageData);
    }

    @RequiresAuthentication
    @GetMapping("/changeUserStatue")
    @RequiresRoles(value = {"admin"},logical = Logical.OR)     //表示是普通用户 或者 admin用户可访问
    public Result changeUserStatue(@RequestParam Long id) {
        User user = userService.getById(id);

        Integer status = user.getStatus();

        //   1表示被停用
        if (status == 1) {
            user.setStatus(0);
        } else {
            user.setStatus(1);
        }

        userService.updateById(user);

        return Result.succ(null);
    }


    /**
     * 处理头像上传
     * 注意 需要手动修改 tomcat的上传限制大小     本地上传版
     * 上传到的是本地
     * 所以数据库中 应该保存 文件的本地地址 OK
     * 加载图片时 又要写一个接口
     *
     * @return
     */
//    @RequiresAuthentication
//    @PostMapping("/avatarupload")
//    public Result avatarUpload(@RequestParam("file") MultipartFile file) {
//
//
//        //如果文件名为空  用了Spring工具包判断空
//        if (file.isEmpty()) {
//            return Result.fail("上传寂寞");
//        }
//
//        //获取文件名(OriginalFilename)包括扩展名
//        String OriginalFilename = file.getOriginalFilename();
//
//        //为了防止别人的文件覆盖掉了 所以名字加上时间戳
//        String uploadFileName = System.currentTimeMillis() + "." + OriginalFilename.substring(OriginalFilename.indexOf(".") + 1);
//
//        //这样文件名就是 时间戳 + 扩展名
//        log.info("头像上传:" + uploadFileName);
//
//        //上传保存地址设置  \\表示 转义符\
//        //注意末尾也要加上\\
//        //！！！！！！！！！！！！！！保存到静态资源路径
//        String filepath = "C:\\Users\\28773\\IdeaProjects\\GitProjects\\MarkerHub_vueblog\\vueblog-master\\vueblog-java\\src\\main\\resources\\static\\avatar\\";
////        String filepath = "static\\avatar";
//        //创建文件哈
//        File dest = new File(filepath + uploadFileName);
//
//        //确保filepath存在
//        if (!dest.getParentFile().exists()) {
//            dest.getParentFile().mkdir();
//        }
//
//        //开始拷贝文件
//        try {
//            file.transferTo(dest);
//        } catch (IOException e) {
//            //可能会出现 硬盘不够等等请求
//            e.printStackTrace();
//            return Result.fail("上传失败");
//        }
//
//
//        //成功上传到本地后 保存到数据库
//        //获取用户id
//        Long id = ShiroUtil.getProfile().getId();
//        User user = userService.getById(id);
//
//        user.setAvatar("http://localhost:8081/avatar/" + uploadFileName);
//
//        userService.updateById(user);
//        return Result.succ(MapUtil.builder()
//                .put("id", user.getId())
//                .put("username", user.getUsername())
//                .put("avatar", user.getAvatar())
//                .put("email", user.getEmail())
//                .put("description", user.getDescription())
//                .map());
//    }


    /**
     *    七牛云版本
     * @param file
     * @return
     */
    @RequiresAuthentication
    @PostMapping("/avatarupload")
    public Result avatarUpload(@RequestParam("file") MultipartFile file) {


        //如果文件名为空  用了Spring工具包判断空
        if (file.isEmpty()) {
            return Result.fail("上传寂寞");
        }

        String originalFilename = file.getOriginalFilename();//获取图片原始文件名
        int index = originalFilename.lastIndexOf(".");
        String extention = originalFilename.substring(index);//获得图片后缀名  .jpg
        String fileName = UUID.randomUUID().toString() + extention; //进行拼接
        fileName = fileName.replace("-", ""); //将文件路径中的-替换掉
//        try {
        //使用工具类将文件上传到七牛云服务器
        String filePath = null;
        try {
            filePath = QiniuUtils.upload2Qiniu(file.getBytes(), fileName);
        } catch (IOException e) {
            System.out.println("上传失败");
        }

        //成功上传到本地后 保存到数据库
        //获取用户id
        Long id = ShiroUtil.getProfile().getId();
        User user = userService.getById(id);

        user.setAvatar(filePath);

        userService.updateById(user);
        return Result.succ(MapUtil.builder()
                .put("id", user.getId())
                .put("username", user.getUsername())
                .put("avatar", user.getAvatar())
                .put("email", user.getEmail())
                .put("description", user.getDescription())
                .map());
    }

}
